﻿using System;
using System.IO;
using System.Windows.Forms;
using Brain.Build;
using Brain.Editor.Controls;
using Brain.Windows;
using WeifenLuo.WinFormsUI.Docking;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.Xna.Framework;

namespace Brain.Editor
{
    /// <summary>
    /// The Main Editor class
    /// </summary>
    public partial class MainEditor : Form, IEditorForm
    {
        public ContentManagerForm ContentManagerForm;

        public DockableXNAViewControl XnaViewControl;

        /// <summary>
        /// Makes a new instance of the Main Editor class
        /// </summary>
        public MainEditor()
        {
            // Design generated code
            InitializeComponent();

            MakeDefaultFactory();

            XnaViewControl = new DockableXNAViewControl();
            XnaViewControl.ViewControl.OnStart += new SetVoid(ViewControl_OnStart);
            XnaViewControl.ViewControl.OnDraw += new SetVoid(ViewControl_OnDraw);

            XnaViewControl.Show(FormDockPanel, DockState.DockRight);
            ContentManagerForm = new ContentManagerForm();
            ContentManagerForm.Show(FormDockPanel, DockState.DockLeftAutoHide);
        }

        private void ViewControl_OnDraw()
        {
            if (this.XnaViewControl.ViewControl.PickingManager3D != null)
            {
                IPickingManager3D picker = this.XnaViewControl.ViewControl.PickingManager3D;
                if (picker.SelectedWorldObject != null)
                {
                    IPickedObject obj = picker.SelectedWorldObject;

                    string X = null;
                    string Y = null;
                    string Z = null;
                    switch (picker.Mode)
                    {
                        case ManipulationMode3D.Translation:
                            {
                                X = FloatUtil.Format(obj.Position.X, 3);
                                Y = FloatUtil.Format(obj.Position.Y, 3);
                                Z = FloatUtil.Format(obj.Position.Z, 3);
                            }
                            break;
                        case ManipulationMode3D.Rotation:
                            {
                                Vector3 rot = Vector3Util.ToDegrees(obj.RotationRadians);
                                X = FloatUtil.Format(rot.X, 1);
                                Y = FloatUtil.Format(rot.Y, 1);
                                Z = FloatUtil.Format(rot.Z, 1);
                            }
                            break;
                        case ManipulationMode3D.Scale:
                            {
                                X = FloatUtil.Format(obj.Scale.X, 3);
                                Y = FloatUtil.Format(obj.Scale.Y, 3);
                                Z = FloatUtil.Format(obj.Scale.Z, 3);
                            }
                            break;
                    }

                    this.text_X.Text = X;
                    this.text_Y.Text = Y;
                    this.text_Z.Text = Z;
                }
            }
        }

        private void MainEditor_FormClosing(object sender, FormClosingEventArgs e)
        {
        }

        void ViewControl_OnStart()
        {
            Engine.Instance.Editor = this;
        }

        public void NewLevel()
        {
            this.XnaViewControl.ViewControl.NewLevel();
            Engine.Instance.Editor = this;
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            NewLevel();
        }
        /// <summary>
        /// Loads the Welcome Form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainEditor_Load(object sender, System.EventArgs e)
        {
            //Engine.Instance.Editor = this;

            /*string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "DockPanel.config");

            if (File.Exists(configFile))
            {
                FormDockPanel.LoadFromXml(configFile, null);
            }*/
        }

        public void MakeInterfaceHolder(object selected)
        {
            //Panel panel = this.panel_Options.Panel;
            //panel.Controls.Clear();
            //InterfaceHolder holder = new InterfaceHolder(panel, selected);
        }

        #region Factory

        public Dictionary<string, ToolStripMenuItem> Items;

        /// <summary>
        /// Adds an object to the Factory List
        /// </summary>
        /// <param name="type">If not null, the object will be instanced using this Type. If null, only the Made 
        /// event will be called</param>
        /// <param name="made">Event when the object is made/is going to be made</param>
        /// <param name="Text">Title of the Factory Object</param>
        public void AddFactoryType(Type type, SetObject made, string Text, string parent)
        {
            if (Items == null)
            {
                Items = new Dictionary<string, ToolStripMenuItem>();
            }            

            FactoryObject factory = new FactoryObject();
            factory.Type = type;
            factory.Name = Text;
            factory.Made = made;

            ToolStripMenuItem item = new ToolStripMenuItem(factory.Name);
            item.Tag = factory;
            item.Click += factory_Select;

            this.Items.Add(Text, item);
            if (!string.IsNullOrEmpty(parent))
            {
                if (!this.Items.ContainsKey(parent))
                {
                    ToolStripMenuItem par = new ToolStripMenuItem();
                    par.Text = parent;
                    this.factoryToolStripMenuItem.DropDownItems.Add(par);
                    this.Items.Add(parent, par);
                }

                ToolStripMenuItem paren = this.Items[parent];
                paren.DropDownItems.Add(item);
            }
            else
            {
                this.factoryToolStripMenuItem.DropDownItems.Add(item);
            }
        }

        /// <summary>
        /// Makes the Default Factory objects
        /// </summary>
        private void MakeDefaultFactory()
        {
            AddFactoryType(typeof(Sprite), delegate(object o)
            {
                Sprite sp = o as Sprite;
                sp.Rendering = SpriteRendering.Rendered;
            }, "2D - Sprite", "2D");

            AddFactoryType(null, delegate(object o)
            {
                MakeWorldObjectForm form = new MakeWorldObjectForm();
                form.Show();
            }, "3D - World Object", "3D");

            AddFactoryType(null, delegate(object o)
            {
                MakeTerrainForm form = new MakeTerrainForm();
                form.Show();
            }, "3D - Terrain", "3D");
        }

        /// <summary>
        /// Makes the object the user selected on the Factory,
        /// and add it to the Engine's first GameScreen. Also,
        /// if it's a Sprite/WorldObject, will set the Rendering
        /// to Rendering.Rendered
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void factory_Select(object sender, EventArgs e)
        {
            if (sender is ToolStripMenuItem)
            {
                ToolStripMenuItem item = sender as ToolStripMenuItem;
                FactoryObject obj = item.Tag as FactoryObject;
                GameScreen s = Engine.Instance.ScreenManager.GetScreen(0);
                obj.MakeNew(s);
            }
        }

        #endregion

        #region File Operations

        /// <summary>
        /// Saves the Level
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Engine.Instance.Editor = this;

            if (string.IsNullOrEmpty(Engine.Instance.SerializationManager.SceneData.RootFolder))
            {
                FolderBrowserDialog levelFolder = new FolderBrowserDialog();
                levelFolder.Description = "Choose a folder to save your Game";
                levelFolder.ShowNewFolderButton = true;

                if (levelFolder.ShowDialog() == DialogResult.OK)
                {
                    string folder = levelFolder.SelectedPath;
                    string name;
                    if (InputTextDialog.Show("Choose your Level Name", "Name your level", out name) == DialogResult.OK)
                    {
                        Engine.Instance.SerializationManager.SceneData.RootFolder = folder;
                        Engine.Instance.SerializationManager.SceneData.LevelName = name;
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }

            string levelFile = Path.Combine(Path.Combine(
                Engine.Instance.SerializationManager.SceneData.RootFolder, 
                Engine.Instance.SerializationManager.SceneData.LevelName + ".brain"));
                
            if (File.Exists(levelFile))
            {
                File.Delete(levelFile);
            }
            using (FileStream stream = new FileStream(levelFile, FileMode.Create))
            {
                Engine.Instance.SerializationManager.Serialize(stream, SerializationType.XML);
            }

            /*string dataBaseFile = Path.Combine(Path.Combine(Engine.Instance.SerializationManager.SceneData.RootFolder, "Database.data"));
            if (File.Exists(dataBaseFile))
            {
                File.Delete(dataBaseFile);
            }
            using (FileStream stream = new FileStream(dataBaseFile, FileMode.Create))
            {
                Engine.Instance.SerializationManager.SerializeUnique(stream, FileType.XML, Engine.Instance.EditorManager.DatabaseManager);
            }

            for (int i = 0; i < Engine.Instance.SerializationManager.SceneData.ContentProject.Files.Count; i++)
            {
                SceneContentFile file = Engine.Instance.SerializationManager.SceneData.ContentProject.Files[i];
                /*if (file.SaveOnEditorSave && file.LoadedData != null)
                {
                    // Save the file
                    if (file.LoadedData is IEditorNeedsSave)
                    {
                        IEditorNeedsSave editorFile = file.LoadedData as IEditorNeedsSave;
                        editorFile.EditorSaving(file);
                    }
                }*/
            //}
        }
        /// <summary>
        /// Opens a Level
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Brain Scene Files|*.brain";
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                NewLevel();                

                using (FileStream str = new FileStream(openFileDialog.FileName, FileMode.Open))
                {
                    Engine.Instance.SerializationManager.Deserialize(str, SerializationType.XML);
                }

                string root = Path.GetDirectoryName(openFileDialog.FileName);
                string levelName = Path.GetFileNameWithoutExtension(openFileDialog.FileName);
                Engine.Instance.SerializationManager.SceneData.RootFolder = root;
                Engine.Instance.SerializationManager.SceneData.LevelName = levelName;
            }
        }



        

        #endregion
        
        private void track_Frame_ValueChanged(object sender, EventArgs e)
        {
            if (Engine.Instance != null)
            {
                //Engine.Instance.AnimationManager.CurrentFrame = this.track_Frame.Value;
            }
        }

        #region Game

        private void databaseToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            DatabaseListForm data = new DatabaseListForm();
            data.Show();
        }
        private void contentManagerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ContentManagerForm.IsDisposed)
            {
                ContentManagerForm = new ContentManagerForm();
                ContentManagerForm.Show(FormDockPanel, DockState.DockLeftAutoHide);
            }
        }
        #endregion

        private void fileConverterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ConversorForm form = new ConversorForm();
            form.Show();
        }

        

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Brain 2 Game Engine, focusing on making the Editor, no time for About message box... by LAR Gaming -> Lucas Assis Ribeiro");
        }

        private void button_EditTerrain_Click(object sender, EventArgs e)
        {
            //this.XnaViewControl.Contro.PickingManager3D.EnableTerrainEditting();
        }

        private void numeric_TerrainSize_ValueChanged(object sender, EventArgs e)
        {
            //this.dockedXNAViewControl1.ViewControl.PickingManager3D.SetTerrainEdittingSize((float)this.numeric_TerrainSize.Value);
        }

        private void numeric_TerrainStrength_ValueChanged(object sender, EventArgs e)
        {
            //this.dockedXNAViewControl1.ViewControl.PickingManager3D.SetTerrainEdittingStrength((float)this.numeric_TerrainStrength.Value);
        }

        private void visualScriptingToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            VisualScriptMaker maker = new VisualScriptMaker(this);
            maker.Show(FormDockPanel, DockState.DockBottomAutoHide);
        }

        private void makeGameDataToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SceneOptionsForm options = new SceneOptionsForm();
            options.ShowDialog();
        }

        private void pluginPackerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PluginPacker packer = new PluginPacker();
            packer.ShowDialog();
        }

        private void translationButton_Click(object sender, EventArgs e)
        {
            if (this.XnaViewControl.ViewControl.PickingManager3D != null)
            {
                this.XnaViewControl.ViewControl.PickingManager3D.Mode = ManipulationMode3D.Translation;
            }
        }

        private void rotationButton_Click(object sender, EventArgs e)
        {
            if (this.XnaViewControl.ViewControl.PickingManager3D != null)
            {
                this.XnaViewControl.ViewControl.PickingManager3D.Mode = ManipulationMode3D.Rotation;
            }
        }

        private void scaleButton_Click(object sender, EventArgs e)
        {
            if (this.XnaViewControl.ViewControl.PickingManager3D != null)
            {
                this.XnaViewControl.ViewControl.PickingManager3D.Mode = ManipulationMode3D.Scale;
            }
        }

        private void minusGridButton_Click(object sender, EventArgs e)
        {
            if (this.XnaViewControl.ViewControl.PickingManager3D != null)
            {
                this.XnaViewControl.ViewControl.PickingManager3D.LessGrid();
            }
        }

        private void plusGridButton_Click(object sender, EventArgs e)
        {
            if (this.XnaViewControl.ViewControl.PickingManager3D != null)
            {
                this.XnaViewControl.ViewControl.PickingManager3D.MoreGrid();
            }
        }


    }
}
